home *** CD-ROM | disk | FTP | other *** search
- /* $Id: nurbsutl.c,v 1.1 1996/09/27 01:19:39 brianp Exp $ */
-
- /*
- * Mesa 3-D graphics library
- * Version: 2.0
- * Copyright (C) 1995-1996 Brian Paul
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-
- /*
- * $Log: nurbsutl.c,v $
- * Revision 1.1 1996/09/27 01:19:39 brianp
- * Initial revision
- *
- */
-
-
- /*
- * NURBS implementation written by Bogdan Sikorski (bogdan@cira.it)
- * See README2 for more info.
- */
-
-
- #include <math.h>
- #include "nurbs.h"
-
- GLenum
- test_knot(GLint nknots, GLfloat *knot, GLint order)
- {
- GLsizei i;
- GLint knot_mult;
- GLfloat tmp_knot;
-
- tmp_knot=knot[0];
- knot_mult=1;
- for(i=1;i<nknots;i++)
- {
- if(knot[i] < tmp_knot)
- return GLU_NURBS_ERROR4;
- if(fabs(tmp_knot-knot[i]) > EPSILON)
- {
- if(knot_mult>order)
- return GLU_NURBS_ERROR5;
- knot_mult=1;
- tmp_knot=knot[i];
- }
- else
- ++knot_mult;
- }
- return GLU_NO_ERROR;
- }
-
- /* qsort function */
- static int
- knot_sort(const void *a, const void *b)
- {
- GLfloat x,y;
-
- x=*((GLfloat *)a);
- y=*((GLfloat *)b);
- if(fabs(x-y) < EPSILON)
- return 0;
- if(x > y)
- return 1;
- return -1;
- }
-
- /* insert into dest knot all values within the valid range from src knot */
- /* that do not appear in dest */
- void
- collect_unified_knot(knot_str_type *dest, knot_str_type *src,
- GLfloat maximal_min_knot, GLfloat minimal_max_knot)
- {
- GLfloat *src_knot,*dest_knot;
- GLint src_t_min,src_t_max,dest_t_min,dest_t_max;
- GLint src_nknots,dest_nknots;
- GLint i,j,k,new_cnt;
- GLboolean not_found_flag;
-
- src_knot=src->unified_knot;
- dest_knot=dest->unified_knot;
- src_t_min=src->t_min;
- src_t_max=src->t_max;
- dest_t_min=dest->t_min;
- dest_t_max=dest->t_max;
- src_nknots=src->unified_nknots;
- dest_nknots=dest->unified_nknots;
-
- k=new_cnt=dest_nknots;
- for(i=src_t_min;i<=src_t_max;i++)
- if(src_knot[i] - maximal_min_knot > -EPSILON &&
- src_knot[i] - minimal_max_knot < EPSILON)
- {
- not_found_flag=GL_TRUE;
- for(j=dest_t_min;j<=dest_t_max;j++)
- if(fabs(dest_knot[j]-src_knot[i]) < EPSILON)
- {
- not_found_flag=GL_FALSE;
- break;
- }
- if(not_found_flag)
- {
- /* knot from src is not in dest - add this knot to dest */
- dest_knot[k++]=src_knot[i];
- ++new_cnt;
- ++(dest->t_max); /* the valid range widens */
- ++(dest->delta_nknots); /* increment the extra knot value counter */
- }
- }
- dest->unified_nknots=new_cnt;
- qsort((void *)dest_knot,(size_t)new_cnt,(size_t)sizeof(GLfloat),
- &knot_sort);
- }
-
- /* basing on the new common knot range for all attributes set */
- /* t_min and t_max values for each knot - they will be used later on */
- /* by explode_knot() and calc_new_ctrl_pts */
- static void
- set_new_t_min_t_max(knot_str_type *geom_knot, knot_str_type *color_knot,
- knot_str_type *normal_knot, knot_str_type *texture_knot,
- GLfloat maximal_min_knot, GLfloat minimal_max_knot)
- {
- GLuint t_min,t_max,cnt;
-
- if(minimal_max_knot-maximal_min_knot < EPSILON)
- {
- /* knot common range empty */
- geom_knot->t_min=geom_knot->t_max=0;
- color_knot->t_min=color_knot->t_max=0;
- normal_knot->t_min=normal_knot->t_max=0;
- texture_knot->t_min=texture_knot->t_max=0;
- }
- else
- {
- if(geom_knot->unified_knot!=NULL)
- {
- cnt=geom_knot->unified_nknots;
- for(t_min=0;t_min<cnt;t_min++)
- if(fabs((geom_knot->unified_knot)[t_min] - maximal_min_knot) <
- EPSILON)
- break;
- for(t_max=cnt-1;t_max;t_max--)
- if(fabs((geom_knot->unified_knot)[t_max] - minimal_max_knot) <
- EPSILON)
- break;
- }
- else
- if(geom_knot->nknots)
- {
- cnt=geom_knot->nknots;
- for(t_min=0;t_min<cnt;t_min++)
- if(fabs((geom_knot->knot)[t_min] - maximal_min_knot) < EPSILON)
- break;
- for(t_max=cnt-1;t_max;t_max--)
- if(fabs((geom_knot->knot)[t_max] - minimal_max_knot) < EPSILON)
- break;
- }
- geom_knot->t_min=t_min;
- geom_knot->t_max=t_max;
- if(color_knot->unified_knot!=NULL)
- {
- cnt=color_knot->unified_nknots;
- for(t_min=0;t_min<cnt;t_min++)
- if(fabs((color_knot->unified_knot)[t_min] - maximal_min_knot) <
- EPSILON)
- break;
- for(t_max=cnt-1;t_max;t_max--)
- if(fabs((color_knot->unified_knot)[t_max] - minimal_max_knot) <
- EPSILON)
- break;
- color_knot->t_min=t_min;
- color_knot->t_max=t_max;
- }
- if(normal_knot->unified_knot!=NULL)
- {
- cnt=normal_knot->unified_nknots;
- for(t_min=0;t_min<cnt;t_min++)
- if(fabs((normal_knot->unified_knot)[t_min] - maximal_min_knot) <
- EPSILON)
- break;
- for(t_max=cnt-1;t_max;t_max--)
- if(fabs((normal_knot->unified_knot)[t_max] - minimal_max_knot) <
- EPSILON)
- break;
- normal_knot->t_min=t_min;
- normal_knot->t_max=t_max;
- }
- if(texture_knot->unified_knot!=NULL)
- {
- cnt=texture_knot->unified_nknots;
- for(t_min=0;t_min<cnt;t_min++)
- if(fabs((texture_knot->unified_knot)[t_min] - maximal_min_knot)
- < EPSILON)
- break;
- for(t_max=cnt-1;t_max;t_max--)
- if(fabs((texture_knot->unified_knot)[t_max] - minimal_max_knot)
- < EPSILON)
- break;
- texture_knot->t_min=t_min;
- texture_knot->t_max=t_max;
- }
- }
- }
-
- /* modify all knot valid ranges in such a way that all have the same */
- /* range, common to all knots */
- /* do this by knot insertion */
- GLenum
- select_knot_working_range(GLUnurbsObj *nobj,knot_str_type *geom_knot,
- knot_str_type *color_knot, knot_str_type *normal_knot,
- knot_str_type *texture_knot)
- {
- GLint max_nknots;
- GLfloat maximal_min_knot,minimal_max_knot;
- GLint i;
-
- /* find the maximum modified knot length */
- max_nknots=geom_knot->nknots;
- if(color_knot->unified_knot)
- max_nknots+=color_knot->nknots;
- if(normal_knot->unified_knot)
- max_nknots+=normal_knot->nknots;
- if(texture_knot->unified_knot)
- max_nknots+=texture_knot->nknots;
- maximal_min_knot=(geom_knot->knot)[geom_knot->t_min];
- minimal_max_knot=(geom_knot->knot)[geom_knot->t_max];
- /* any attirb data ? */
- if(max_nknots!=geom_knot->nknots)
- {
- /* allocate space for the unified knots */
- if((geom_knot->unified_knot=
- (GLfloat *)malloc(sizeof(GLfloat)*max_nknots))==NULL)
- {
- call_user_error(nobj,GLU_OUT_OF_MEMORY);
- return GLU_ERROR;
- }
- /* copy the original knot to the unified one */
- geom_knot->unified_nknots=geom_knot->nknots;
- for(i=0;i<geom_knot->nknots;i++)
- (geom_knot->unified_knot)[i]=(geom_knot->knot)[i];
- if(color_knot->unified_knot)
- {
- if((color_knot->knot)[color_knot->t_min] - maximal_min_knot >
- EPSILON)
- maximal_min_knot=(color_knot->knot)[color_knot->t_min];
- if(minimal_max_knot - (color_knot->knot)[color_knot->t_max] >
- EPSILON)
- minimal_max_knot=(color_knot->knot)[color_knot->t_max];
- if((color_knot->unified_knot=
- (GLfloat *)malloc(sizeof(GLfloat)*max_nknots))==NULL)
- {
- free(geom_knot->unified_knot);
- call_user_error(nobj,GLU_OUT_OF_MEMORY);
- return GLU_ERROR;
- }
- /* copy the original knot to the unified one */
- color_knot->unified_nknots=color_knot->nknots;
- for(i=0;i<color_knot->nknots;i++)
- (color_knot->unified_knot)[i]=(color_knot->knot)[i];
- }
- if(normal_knot->unified_knot)
- {
- if((normal_knot->knot)[normal_knot->t_min] - maximal_min_knot >
- EPSILON)
- maximal_min_knot=(normal_knot->knot)[normal_knot->t_min];
- if(minimal_max_knot - (normal_knot->knot)[normal_knot->t_max] >
- EPSILON)
- minimal_max_knot=(normal_knot->knot)[normal_knot->t_max];
- if((normal_knot->unified_knot=
- (GLfloat *)malloc(sizeof(GLfloat)*max_nknots))==NULL)
- {
- free(geom_knot->unified_knot);
- free(color_knot->unified_knot);
- call_user_error(nobj,GLU_OUT_OF_MEMORY);
- return GLU_ERROR;
- }
- /* copy the original knot to the unified one */
- normal_knot->unified_nknots=normal_knot->nknots;
- for(i=0;i<normal_knot->nknots;i++)
- (normal_knot->unified_knot)[i]=(normal_knot->knot)[i];
- }
- if(texture_knot->unified_knot)
- {
- if((texture_knot->knot)[texture_knot->t_min] - maximal_min_knot >
- EPSILON)
- maximal_min_knot=(texture_knot->knot)[texture_knot->t_min];
- if(minimal_max_knot - (texture_knot->knot)[texture_knot->t_max] >
- EPSILON)
- minimal_max_knot=(texture_knot->knot)[texture_knot->t_max];
- if((texture_knot->unified_knot=
- (GLfloat *)malloc(sizeof(GLfloat)*max_nknots))==NULL)
- {
- free(geom_knot->unified_knot);
- free(color_knot->unified_knot);
- free(normal_knot->unified_knot);
- call_user_error(nobj,GLU_OUT_OF_MEMORY);
- return GLU_ERROR;
- }
- /* copy the original knot to the unified one */
- texture_knot->unified_nknots=texture_knot->nknots;
- for(i=0;i<texture_knot->nknots;i++)
- (texture_knot->unified_knot)[i]=(texture_knot->knot)[i];
- }
- /* work on the geometry knot with all additional knot values */
- /* appearing in attirbutive knots */
- if(minimal_max_knot-maximal_min_knot < EPSILON)
- {
- /* empty working range */
- geom_knot->unified_nknots=0;
- color_knot->unified_nknots=0;
- normal_knot->unified_nknots=0;
- texture_knot->unified_nknots=0;
- }
- else
- {
- if(color_knot->unified_knot)
- collect_unified_knot(geom_knot,color_knot,maximal_min_knot,
- minimal_max_knot);
- if(normal_knot->unified_knot)
- collect_unified_knot(geom_knot,normal_knot,maximal_min_knot,
- minimal_max_knot);
- if(texture_knot->unified_knot)
- collect_unified_knot(geom_knot,texture_knot,maximal_min_knot,
- minimal_max_knot);
- /* since we have now built the "unified" geometry knot */
- /* add same knot values to all attributive knots */
- if(color_knot->unified_knot)
- collect_unified_knot(color_knot,geom_knot,maximal_min_knot,
- minimal_max_knot);
- if(normal_knot->unified_knot)
- collect_unified_knot(normal_knot,geom_knot,maximal_min_knot,
- minimal_max_knot);
- if(texture_knot->unified_knot)
- collect_unified_knot(texture_knot,geom_knot,maximal_min_knot,
- minimal_max_knot);
- }
- }
- set_new_t_min_t_max(geom_knot,color_knot,normal_knot,texture_knot,
- maximal_min_knot,minimal_max_knot);
- return GLU_NO_ERROR;
- }
-
- void
- free_unified_knots(knot_str_type *geom_knot, knot_str_type *color_knot,
- knot_str_type *normal_knot, knot_str_type *texture_knot)
- {
- if(geom_knot->unified_knot)
- free(geom_knot->unified_knot);
- if(color_knot->unified_knot)
- free(color_knot->unified_knot);
- if(normal_knot->unified_knot)
- free(normal_knot->unified_knot);
- if(texture_knot->unified_knot)
- free(texture_knot->unified_knot);
- }
-
- GLenum
- explode_knot(knot_str_type *the_knot)
- {
- GLfloat *knot,*new_knot;
- GLint nknots,n_new_knots=0;
- GLint t_min,t_max;
- GLint ord;
- GLsizei i,j,k;
- GLfloat tmp_float;
-
- if(the_knot->unified_knot)
- {
- knot=the_knot->unified_knot;
- nknots=the_knot->unified_nknots;
- }
- else
- {
- knot=the_knot->knot;
- nknots=the_knot->nknots;
- }
- ord=the_knot->order;
- t_min=the_knot->t_min;
- t_max=the_knot->t_max;
-
- for(i=t_min;i<=t_max;)
- {
- tmp_float=knot[i];
- for(j=0;j<ord && (i+j)<=t_max;j++)
- if(fabs(tmp_float-knot[i+j])>EPSILON)
- break;
- n_new_knots+=ord-j;
- i+=j;
- }
- /* alloc space for new_knot */
- if((new_knot=(GLfloat *)malloc(sizeof(GLfloat)*(nknots+n_new_knots)))==NULL)
- {
- return GLU_OUT_OF_MEMORY;
- }
- /* fill in new knot */
- for(j=0;j<t_min;j++)
- new_knot[j]=knot[j];
- for(i=j;i<=t_max;i++)
- {
- tmp_float=knot[i];
- for(k=0;k<ord;k++)
- {
- new_knot[j++]=knot[i];
- if(tmp_float==knot[i+1])
- i++;
- }
- }
- for(i=t_max+1;i<(int)nknots;i++)
- new_knot[j++]=knot[i];
- /* fill in the knot structure */
- the_knot->new_knot=new_knot;
- the_knot->delta_nknots+=n_new_knots;
- the_knot->t_max+=n_new_knots;
- return GLU_NO_ERROR;
- }
-
- GLenum
- calc_alphas(knot_str_type *the_knot)
- {
- GLfloat tmp_float;
- int i,j,k,m,n;
- int order;
- GLfloat *alpha,*alpha_new,*tmp_alpha;
- GLfloat denom;
- GLfloat *knot,*new_knot;
-
-
- knot=the_knot->knot;
- order=the_knot->order;
- new_knot=the_knot->new_knot;
- n=the_knot->nknots-the_knot->order;
- m=n+the_knot->delta_nknots;
- if((alpha=(GLfloat *)malloc(sizeof(GLfloat)*n*m))==NULL)
- {
- return GLU_OUT_OF_MEMORY;
- }
- if((alpha_new=(GLfloat *)malloc(sizeof(GLfloat)*n*m))==NULL)
- {
- free(alpha);
- return GLU_OUT_OF_MEMORY;
- }
- for(j=0;j<m;j++)
- {
- for(i=0;i<n;i++)
- {
- if((knot[i] <= new_knot[j]) && (new_knot[j] < knot[i+1]))
- tmp_float=1.0;
- else
- tmp_float=0.0;
- alpha[i+j*n]=tmp_float;
- }
- }
- for(k=1;k<order;k++)
- {
- for(j=0;j<m;j++)
- for(i=0;i<n;i++)
- {
- denom=knot[i+k]-knot[i];
- if(fabs(denom)<EPSILON)
- tmp_float=0.0;
- else
- tmp_float=(new_knot[j+k]-knot[i])/denom*
- alpha[i+j*n];
- denom=knot[i+k+1]-knot[i+1];
- if(fabs(denom)>EPSILON)
- tmp_float+=(knot[i+k+1]-new_knot[j+k])/denom*
- alpha[(i+1)+j*n];
- alpha_new[i+j*n]=tmp_float;
- }
- tmp_alpha=alpha_new;
- alpha_new=alpha;
- alpha=tmp_alpha;
- }
- the_knot->alpha=alpha;
- free(alpha_new);
- return GLU_NO_ERROR;
- }
-
- GLenum
- calc_new_ctrl_pts(GLfloat *ctrl,GLint stride,knot_str_type *the_knot,
- GLint dim,GLfloat **new_ctrl,GLint *ncontrol)
- {
- GLsizei i,j,k,l,m,n;
- GLsizei index1,index2;
- GLfloat *alpha;
- GLfloat *new_knot;
-
- new_knot=the_knot->new_knot;
- n=the_knot->nknots-the_knot->order;
- alpha=the_knot->alpha;
-
- m=the_knot->t_max+1-the_knot->t_min-the_knot->order;
- k=the_knot->t_min;
- /* allocate space for new control points */
- if((*new_ctrl=(GLfloat *)malloc(sizeof(GLfloat)*dim*m))==NULL)
- {
- return GLU_OUT_OF_MEMORY;
- }
- for(j=0;j<m;j++)
- {
- for(l=0;l<dim;l++)
- (*new_ctrl)[j*dim+l]=0.0;
- for(i=0;i<n;i++)
- {
- index1=i+(j+k)*n;
- index2=i*stride;
- for(l=0;l<dim;l++)
- (*new_ctrl)[j*dim+l]+=alpha[index1]*ctrl[index2+l];
- }
- }
- *ncontrol=(GLint)m;
- return GLU_NO_ERROR;
- }
-
- static GLint
- calc_factor(GLfloat *pts,GLint order,GLint indx,GLint stride,GLfloat tolerance,
- GLint dim)
- {
- GLdouble model[16],proj[16];
- GLint viewport[4];
- GLdouble x,y,z,w,winx1,winy1,winz,winx2,winy2;
- GLint i;
- GLdouble len,dx,dy;
-
- glGetDoublev(GL_MODELVIEW_MATRIX,model);
- glGetDoublev(GL_PROJECTION_MATRIX,proj);
- glGetIntegerv(GL_VIEWPORT,viewport);
- if(dim==4)
- {
- w=(GLdouble)pts[indx+3];
- x=(GLdouble)pts[indx]/w;
- y=(GLdouble)pts[indx+1]/w;
- z=(GLdouble)pts[indx+2]/w;
- gluProject(x,y,z,model,proj,viewport,&winx1,&winy1,&winz);
- len=0.0;
- for(i=1;i<order;i++)
- {
- w=(GLdouble)pts[indx+i*stride+3];
- x=(GLdouble)pts[indx+i*stride]/w;
- y=(GLdouble)pts[indx+i*stride+1]/w;
- z=(GLdouble)pts[indx+i*stride+2]/w;
- if(gluProject(x,y,z,model,proj,viewport,&winx2,&winy2,&winz))
- {
- dx=winx2-winx1;
- dy=winy2-winy1;
- len+=sqrt(dx*dx+dy*dy);
- }
- winx1=winx2; winy1=winy2;
- }
- }
- else
- {
- x=(GLdouble)pts[indx];
- y=(GLdouble)pts[indx+1];
- if(dim==2)
- z=0.0;
- else
- z=(GLdouble)pts[indx+2];
- gluProject(x,y,z,model,proj,viewport,&winx1,&winy1,&winz);
- len=0.0;
- for(i=1;i<order;i++)
- {
- x=(GLdouble)pts[indx+i*stride];
- y=(GLdouble)pts[indx+i*stride+1];
- if(dim==2)
- z=0.0;
- else
- z=(GLdouble)pts[indx+i*stride+2];
- if(gluProject(x,y,z,model,proj,viewport,&winx2,&winy2,&winz))
- {
- dx=winx2-winx1;
- dy=winy2-winy1;
- len+=sqrt(dx*dx+dy*dy);
- }
- winx1=winx2; winy1=winy2;
- }
- }
- len /= tolerance;
- return ((GLint)len+1);
- }
-
- static GLenum
- calc_sampling_3D(new_ctrl_type *new_ctrl, GLfloat tolerance, GLint dim,
- GLint uorder, GLint vorder, GLint **ufactors, GLint **vfactors)
- {
- GLfloat *ctrl;
- GLint tmp_factor1,tmp_factor2;
- GLint ufactor_cnt,vfactor_cnt;
- GLint offset1,offset2,offset3;
- GLint i,j;
-
- ufactor_cnt=new_ctrl->s_bezier_cnt;
- vfactor_cnt=new_ctrl->t_bezier_cnt;
- if((*ufactors=(GLint *)malloc(sizeof(GLint)*ufactor_cnt*3))
- ==NULL)
- {
- return GLU_OUT_OF_MEMORY;
- }
- if((*vfactors=(GLint *)malloc(sizeof(GLint)*vfactor_cnt*3))
- ==NULL)
- {
- free(ufactors);
- return GLU_OUT_OF_MEMORY;
- }
- ctrl=new_ctrl->geom_ctrl;
- offset1=new_ctrl->geom_t_stride*vorder;
- offset2=new_ctrl->geom_s_stride*uorder;
- for(j=0;j<vfactor_cnt;j++)
- {
- *(*vfactors+j*3+1)=tmp_factor1=calc_factor(ctrl,vorder,
- j*offset1,dim,tolerance,dim);
- /* loop ufactor_cnt-1 times */
- for(i=1;i<ufactor_cnt;i++)
- {
- tmp_factor2=calc_factor(ctrl,vorder,
- j*offset1+i*offset2,dim,tolerance,dim);
- if(tmp_factor2>tmp_factor1)
- tmp_factor1=tmp_factor2;
- }
- /* last time for the opposite edge */
- *(*vfactors+j*3+2)=tmp_factor2=calc_factor(ctrl,vorder,
- j*offset1+i*offset2-new_ctrl->geom_s_stride,
- dim,tolerance,dim);
- if(tmp_factor2>tmp_factor1)
- *(*vfactors+j*3)=tmp_factor2;
- else
- *(*vfactors+j*3)=tmp_factor1;
- }
- offset3=new_ctrl->geom_s_stride;
- offset2=new_ctrl->geom_s_stride*uorder;
- for(j=0;j<ufactor_cnt;j++)
- {
- *(*ufactors+j*3+1)=tmp_factor1=calc_factor(ctrl,uorder,
- j*offset2,offset3,tolerance,dim);
- /* loop vfactor_cnt-1 times */
- for(i=1;i<vfactor_cnt;i++)
- {
- tmp_factor2=calc_factor(ctrl,uorder,
- j*offset2+i*offset1,offset3,tolerance,dim);
- if(tmp_factor2>tmp_factor1)
- tmp_factor1=tmp_factor2;
- }
- /* last time for the opposite edge */
- *(*ufactors+j*3+2)=tmp_factor2=calc_factor(ctrl,uorder,
- j*offset2+i*offset1-new_ctrl->geom_t_stride,
- offset3,tolerance,dim);
- if(tmp_factor2>tmp_factor1)
- *(*ufactors+j*3)=tmp_factor2;
- else
- *(*ufactors+j*3)=tmp_factor1;
- }
- return GL_NO_ERROR;
- }
-
- static GLenum
- calc_sampling_2D(GLfloat *ctrl, GLint cnt, GLint order,
- GLfloat tolerance, GLint dim, GLint **factors)
- {
- GLint factor_cnt;
- GLint tmp_factor;
- GLint offset;
- GLint i;
-
- factor_cnt=cnt/order;
- if((*factors=(GLint *)malloc(sizeof(GLint)*factor_cnt))==NULL)
- {
- return GLU_OUT_OF_MEMORY;
- }
- offset=order*dim;
- for(i=0;i<factor_cnt;i++)
- {
- tmp_factor=calc_factor(ctrl,order,i*offset,dim,tolerance,dim);
- if(tmp_factor == 0)
- (*factors)[i]=1;
- else
- (*factors)[i]=tmp_factor;
- }
- return GL_NO_ERROR;
- }
-
- static void
- set_sampling_and_culling( GLUnurbsObj *nobj )
- {
- if(nobj->auto_load_matrix==GL_FALSE)
- {
- GLint i;
- GLfloat m[4];
-
- glPushAttrib( (GLbitfield) (GL_VIEWPORT_BIT | GL_TRANSFORM_BIT));
- for(i=0;i<4;i++)
- m[i]=nobj->sampling_matrices.viewport[i];
- glViewport(m[0],m[1],m[2],m[3]);
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glLoadMatrixf(nobj->sampling_matrices.proj);
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
- glLoadMatrixf(nobj->sampling_matrices.model);
- }
- }
-
- static void
- revert_sampling_and_culling( GLUnurbsObj *nobj )
- {
- if(nobj->auto_load_matrix==GL_FALSE)
- {
- glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
- glPopAttrib();
- }
- }
-
- GLenum
- glu_do_sampling_3D( GLUnurbsObj *nobj, new_ctrl_type *new_ctrl,
- GLint **sfactors, GLint **tfactors)
- {
- GLint dim;
- GLenum err;
-
- *sfactors=NULL;
- *tfactors=NULL;
- dim=nobj->surface.geom.dim;
- set_sampling_and_culling(nobj);
- if((err=calc_sampling_3D(new_ctrl,nobj->sampling_tolerance,dim,
- nobj->surface.geom.sorder,nobj->surface.geom.torder,
- sfactors,tfactors))==GLU_ERROR)
- {
- revert_sampling_and_culling(nobj);
- call_user_error(nobj,err);
- return GLU_ERROR;
- }
- revert_sampling_and_culling(nobj);
- return GLU_NO_ERROR;
- }
-
- GLenum
- glu_do_sampling_2D( GLUnurbsObj *nobj, GLfloat *ctrl, GLint cnt, GLint order,
- GLint dim, GLint **factors)
- {
- GLenum err;
-
- *factors=NULL;
- set_sampling_and_culling(nobj);
- if((err=calc_sampling_2D(ctrl,cnt,order,nobj->sampling_tolerance,dim,
- factors))==GLU_ERROR)
- {
- revert_sampling_and_culling(nobj);
- call_user_error(nobj,err);
- return GLU_ERROR;
- }
- revert_sampling_and_culling(nobj);
- return GLU_NO_ERROR;
- }
-
- /* TODO - i don't like this culling - this one just tests if at least one */
- /* ctrl point lies within the viewport . Also the point_in_viewport() */
- /* should be included in the fnctions for efficiency reasons */
-
- static GLboolean
- point_in_viewport(GLfloat *pt, GLint dim)
- {
- GLdouble model[16],proj[16];
- GLint viewport[4];
- GLdouble x,y,z,w,winx,winy,winz;
-
- glGetDoublev(GL_MODELVIEW_MATRIX,model);
- glGetDoublev(GL_PROJECTION_MATRIX,proj);
- glGetIntegerv(GL_VIEWPORT,viewport);
- if(dim==3)
- {
- x=(GLdouble)pt[0];
- y=(GLdouble)pt[1];
- z=(GLdouble)pt[2];
- gluProject(x,y,z,model,proj,viewport,&winx,&winy,&winz);
- }
- else
- {
- w=(GLdouble)pt[3];
- x=(GLdouble)pt[0]/w;
- y=(GLdouble)pt[1]/w;
- z=(GLdouble)pt[2]/w;
- gluProject(x,y,z,model,proj,viewport,&winx,&winy,&winz);
- }
- if((GLint)winx >= viewport[0] && (GLint)winx < viewport[2] &&
- (GLint)winy >= viewport[1] && (GLint)winy < viewport[3])
- return GL_TRUE;
- return GL_FALSE;
- }
-
- GLboolean
- fine_culling_test_3D(GLUnurbsObj *nobj,GLfloat *pts,GLint s_cnt,GLint t_cnt,
- GLint s_stride,GLint t_stride, GLint dim)
- {
- GLint i,j;
-
- if(nobj->culling==GL_FALSE)
- return GL_FALSE;
- set_sampling_and_culling(nobj);
-
- if(dim==3)
- {
- for(i=0;i<s_cnt;i++)
- for(j=0;j<t_cnt;j++)
- if(point_in_viewport(pts+i*s_stride+j*t_stride,dim))
- {
- revert_sampling_and_culling(nobj);
- return GL_FALSE;
- }
- }
- else
- {
- for(i=0;i<s_cnt;i++)
- for(j=0;j<t_cnt;j++)
- if(point_in_viewport(pts+i*s_stride+j*t_stride,dim))
- {
- revert_sampling_and_culling(nobj);
- return GL_FALSE;
- }
- }
- revert_sampling_and_culling(nobj);
- return GL_TRUE;
- }
-
- /*GLboolean
- fine_culling_test_3D(GLUnurbsObj *nobj,GLfloat *pts,GLint s_cnt,GLint t_cnt,
- GLint s_stride,GLint t_stride, GLint dim)
- {
- GLint visible_cnt;
- GLfloat feedback_buffer[5];
- GLsizei buffer_size;
- GLint i,j;
-
- if(nobj->culling==GL_FALSE)
- return GL_FALSE;
- buffer_size=5;
- set_sampling_and_culling(nobj);
-
- glFeedbackBuffer(buffer_size,GL_2D,feedback_buffer);
- glRenderMode(GL_FEEDBACK);
- if(dim==3)
- {
- for(i=0;i<s_cnt;i++)
- {
- glBegin(GL_LINE_LOOP);
- for(j=0;j<t_cnt;j++)
- glVertex3fv(pts+i*s_stride+j*t_stride);
- glEnd();
- }
- for(j=0;j<t_cnt;j++)
- {
- glBegin(GL_LINE_LOOP);
- for(i=0;i<s_cnt;i++)
- glVertex3fv(pts+i*s_stride+j*t_stride);
- glEnd();
- }
- }
- else
- {
- for(i=0;i<s_cnt;i++)
- {
- glBegin(GL_LINE_LOOP);
- for(j=0;j<t_cnt;j++)
- glVertex4fv(pts+i*s_stride+j*t_stride);
- glEnd();
- }
- for(j=0;j<t_cnt;j++)
- {
- glBegin(GL_LINE_LOOP);
- for(i=0;i<s_cnt;i++)
- glVertex4fv(pts+i*s_stride+j*t_stride);
- glEnd();
- }
- }
- visible_cnt=glRenderMode(GL_RENDER);
-
- revert_sampling_and_culling(nobj);
- return (GLboolean)(visible_cnt==0);
- }*/
-
- GLboolean
- fine_culling_test_2D(GLUnurbsObj *nobj,GLfloat *pts,GLint cnt,
- GLint stride, GLint dim)
- {
- GLint i;
-
- if(nobj->culling==GL_FALSE)
- return GL_FALSE;
- set_sampling_and_culling(nobj);
-
- if(dim==3)
- {
- for(i=0;i<cnt;i++)
- if(point_in_viewport(pts+i*stride,dim))
- {
- revert_sampling_and_culling(nobj);
- return GL_FALSE;
- }
- }
- else
- {
- for(i=0;i<cnt;i++)
- if(point_in_viewport(pts+i*stride,dim))
- {
- revert_sampling_and_culling(nobj);
- return GL_FALSE;
- }
- }
- revert_sampling_and_culling(nobj);
- return GL_TRUE;
- }
-
- /*GLboolean
- fine_culling_test_2D(GLUnurbsObj *nobj,GLfloat *pts,GLint cnt,
- GLint stride, GLint dim)
- {
- GLint visible_cnt;
- GLfloat feedback_buffer[5];
- GLsizei buffer_size;
- GLint i;
-
- if(nobj->culling==GL_FALSE)
- return GL_FALSE;
- buffer_size=5;
- set_sampling_and_culling(nobj);
-
- glFeedbackBuffer(buffer_size,GL_2D,feedback_buffer);
- glRenderMode(GL_FEEDBACK);
- glBegin(GL_LINE_LOOP);
- if(dim==3)
- {
- for(i=0;i<cnt;i++)
- glVertex3fv(pts+i*stride);
- }
- else
- {
- for(i=0;i<cnt;i++)
- glVertex4fv(pts+i*stride);
- }
- glEnd();
- visible_cnt=glRenderMode(GL_RENDER);
-
- revert_sampling_and_culling(nobj);
- return (GLboolean)(visible_cnt==0);
- }*/
-
-